package com.wzcl.app.service.impl;

import com.alibaba.fastjson.JSON;
import com.wzcl.app.dao.model.ActivitySinglePromotion;
import com.wzcl.app.dao.repository.ActivitySinglePromotionRepository;
import com.wzcl.app.model.common.BusinessException;
import com.wzcl.app.model.common.CodeMsg;
import com.wzcl.app.model.common.MyPage;
import com.wzcl.app.model.common.WZCL;
import com.wzcl.app.model.dto.PromotionDto;
import com.wzcl.app.service.ActivitySinglePromotionService;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


@Log4j2
@Service
@Transactional
public class ActivitySinglePromotionServiceImpl implements ActivitySinglePromotionService {

    @Autowired
    private ActivitySinglePromotionRepository repository;

    @Override
    public ActivitySinglePromotion create(PromotionDto promotionDto) {
        //创建活动
        ActivitySinglePromotion activitySinglePromotion = new ActivitySinglePromotion();
        activitySinglePromotion.setActivityId(promotionDto.getActivityId());
        activitySinglePromotion.setOrderNo(promotionDto.getOrderNo());
        activitySinglePromotion.setPromotionType(promotionDto.getPromotionType());
        activitySinglePromotion.setValue(new BigDecimal(promotionDto.getValue()));
        return repository.save(activitySinglePromotion);
    }

    @Override
    public ActivitySinglePromotion update(PromotionDto promotionDto) {
        //校验获取
        ActivitySinglePromotion singlePromotion = getAndCheckById(promotionDto);
        //修改
        singlePromotion.setOrderNo(promotionDto.getOrderNo());
        singlePromotion.setPromotionType(promotionDto.getPromotionType());
        singlePromotion.setValue(new BigDecimal(promotionDto.getValue()));
        return repository.save(singlePromotion);
    }

    @Override
    public ActivitySinglePromotion getById(Integer promotionId) {
        return null;
    }

    @Override
    public ActivitySinglePromotion deleteById(Integer promotionId) {
        ActivitySinglePromotion singlePromotion = getAndCheckById(promotionId);
        //校验获取
        log.info("SinglePromotion:{} Physical deletion", JSON.toJSONString(singlePromotion));
        repository.delete(singlePromotion);
        return singlePromotion;
    }

    @Override
    public void deleteAllByActivityId(Integer activityId) {
        repository.deleteAllByActivityId(activityId);
    }

    @Override
    public void checkValid(PromotionDto promotionDto) {
        if (promotionDto.getPromotionType() == null) {
            throw new BusinessException(CodeMsg.MUST_BE_NOT_NULL, "缺少促销类型");
        }
        if (StringUtils.isBlank(promotionDto.getValue())) {
            throw new BusinessException(CodeMsg.MUST_BE_NOT_NULL, "缺少促销值");
        }
    }

    @Override
    public void checkConflict(List<ActivitySinglePromotion> promotionList) {

    }

    @Override
    public List<ActivitySinglePromotion> findAllByActivityId(Integer activityId) {
        return repository.findAllByActivityIdOrderByOrderNoDesc(activityId);
    }

    @Override
    public MyPage<ActivitySinglePromotion> findPage(PromotionDto promotionDto) {
        return new MyPage<>(repository.findAll(getSpecification(promotionDto),promotionDto.getPageable()));
    }

    @Override
    public BigDecimal computePrice(BigDecimal currentPrice, List<ActivitySinglePromotion> promotions, Map<String,Object> condition) {
        for (ActivitySinglePromotion promotion : promotions){
            if (!(BigDecimal.ZERO.compareTo(currentPrice) < 0)) {
                return BigDecimal.ZERO;
            }
            if (WZCL.ACTIVITY_PROMOTION_TYPE.RATED.equals(promotion.getPromotionType())) {
                currentPrice = promotion.getValue();
            } else if (WZCL.ACTIVITY_PROMOTION_TYPE.AMOUNT.equals(promotion.getPromotionType())) {
                currentPrice = compute(currentPrice, WZCL.OPERATOR_RULE.SUBTRACT, promotion.getValue());
            } else if (WZCL.ACTIVITY_PROMOTION_TYPE.DISCOUNT.equals(promotion.getPromotionType())) {
                currentPrice = compute(currentPrice, WZCL.OPERATOR_RULE.MULTIPLY, promotion.getValue().divide(new BigDecimal("100")));
            }
        }
        return currentPrice.setScale(2, BigDecimal.ROUND_DOWN);
    }

    @Override
    public ActivitySinglePromotion getAndCheckById(Integer id) {
        if (id == null) {
            throw new BusinessException(CodeMsg.MUST_BE_NOT_NULL, "缺少单品促销优惠Id");
        }
        ActivitySinglePromotion singlePromotion = getById(id);
        if (singlePromotion == null) {
            throw new BusinessException(CodeMsg.SINGLE_PROMOTION_NOT_EXIST);
        }
        return singlePromotion;
    }


    public Specification<ActivitySinglePromotion> getSpecification(PromotionDto promotionDto) {
        return new Specification<ActivitySinglePromotion>() {
            @Override
            public Predicate toPredicate(Root<ActivitySinglePromotion> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<Predicate>();
                if (promotionDto.getActivityId() != null) {
                    predicates.add(criteriaBuilder.equal(root.get("activityId"), promotionDto.getActivityId()));
                }
                if (promotionDto.getPromotionType() != null) {
                    predicates.add(criteriaBuilder.equal(root.get("promotionType"), promotionDto.getPromotionType()));
                }
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
    }
}
